<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>高中数学对称图形解析式绘图工具</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <style>
        .function-example {
            cursor: pointer;
            transition: all 0.2s;
        }
        .function-example:hover {
            background-color: #f3f4f6;
        }
    </style>
</head>
<body class="bg-gray-50 font-sans">
    <div class="max-w-7xl mx-auto p-4 md:p-6">
        <h1 class="text-2xl md:text-3xl font-bold text-center text-gray-800 mb-6">对称图形解析式绘图工具</h1>
        
        <!-- 输入区域 -->
        <div class="bg-white rounded-lg shadow-md p-4 md:p-5 mb-6">
            <div class="flex flex-col md:flex-row gap-4">
                <div class="flex-1">
                    <label for="functionInput" class="block text-gray-700 font-medium mb-2">函数解析式</label>
                    <input 
                        type="text" 
                        id="functionInput" 
                        placeholder="请输入函数解析式（使用x作为自变量）"
                        class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                        value="x**2"
                    >
                </div>
                <div class="flex items-end">
                    <button 
                        id="drawBtn" 
                        class="w-full md:w-auto px-6 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors"
                    >
                        绘制图像
                    </button>
                </div>
            </div>
            
            <!-- 示例函数 -->
            <div class="mt-4">
                <p class="text-gray-700 font-medium mb-2">示例函数：</p>
                <div class="grid grid-cols-2 md:grid-cols-4 gap-2">
                    <div class="function-example text-center px-3 py-2 bg-blue-100 text-blue-700 rounded-md" data-func="x**2">y = x²</div>
                    <div class="function-example text-center px-3 py-2 bg-blue-100 text-blue-700 rounded-md" data-func="1/x">y = 1/x</div>
                    <div class="function-example text-center px-3 py-2 bg-blue-100 text-blue-700 rounded-md" data-func="sin(x)">y = sin(x)</div>
                    <div class="function-example text-center px-3 py-2 bg-blue-100 text-blue-700 rounded-md" data-func="sqrt(x)">y = √x</div>
                </div>
            </div>
            
            <div class="mt-4 text-sm text-gray-500">
                提示：支持基本运算（+、-、*、/、**）和常见函数（sin、cos、tan、sqrt、abs等）
            </div>
        </div>
        
        <!-- 绘图区域 -->
        <div class="bg-white rounded-lg shadow-md p-4 md:p-5">
            <canvas id="functionChart" height="400"></canvas>
        </div>
    </div>

    <script>
        // 初始化图表
        const ctx = document.getElementById('functionChart').getContext('2d');
        let functionChart = new Chart(ctx, {
            type: 'scatter',
            data: {
                datasets: [{
                    label: '函数图像',
                    data: [],
                    borderColor: '#3b82f6',
                    backgroundColor: '#3b82f6',
                    borderWidth: 2,
                    pointRadius: 0,
                    fill: false,
                    tension: 0.1,
                    showLine: true,
                    segment: {
                        borderColor: ctx => {
                            // 检测不连续点，如果相邻点差值过大则断开连接
                            const index = ctx.p1DataIndex;
                            const dataset = ctx.chart.data.datasets[0];
                            
                            // 如果没有前一个点，直接返回颜色
                            if (index === 0) return '#3b82f6';
                            
                            const prevPoint = dataset.data[index - 1];
                            const currentPoint = dataset.data[index];
                            
                            // 如果前一个点或当前点是断开点，则不绘制线段
                            if (prevPoint.isDiscontinuity || currentPoint.isDiscontinuity) {
                                return 'transparent';
                            }
                            
                            // 如果相邻点的y值变化过大，则认为是间断点
                            if (Math.abs(currentPoint.y - prevPoint.y) > 20) {
                                return 'transparent';
                            }
                            
                            return '#3b82f6';
                        }
                    }
                }]
            },
            options: {
                responsive: true,
                scales: {
                    x: {
                        type: 'linear',
                        position: 'center',
                        min: -10,
                        max: 10,
                        grid: {
                            color: 'rgba(0, 0, 0, 0.1)'
                        },
                        ticks: {
                            stepSize: 1
                        },
                        title: {
                            display: true,
                            text: 'x轴'
                        }
                    },
                    y: {
                        type: 'linear',
                        position: 'center',
                        min: -10,
                        max: 10,
                        grid: {
                            color: 'rgba(0, 0, 0, 0.1)'
                        },
                        ticks: {
                            stepSize: 1
                        },
                        title: {
                            display: true,
                            text: 'y轴'
                        }
                    }
                },
                plugins: {
                    legend: {
                        display: true
                    },
                    tooltip: {
                        enabled: true,
                        callbacks: {
                            label: function(context) {
                                // 如果是断开点，不显示提示
                                if (context.raw.isDiscontinuity) {
                                    return null;
                                }
                                return `x: ${context.parsed.x.toFixed(2)}, y: ${context.parsed.y.toFixed(2)}`;
                            }
                        }
                    }
                }
            }
        });

        // 生成函数数据
        function generateFunctionData(expression, start = -10, end = 10, step = 0.1) {
            const data = [];
            let prevY = null;
            
            for (let x = start; x <= end; x += step) {
                try {
                    // 使用Function构造函数替代eval，提高安全性
                    const func = new Function('x', `with(Math) { return ${expression}; }`);
                    const y = func(x);
                    
                    // 过滤无效值
                    if (!isNaN(y) && isFinite(y)) {
                        // 检查是否是不连续点（与上一个点差值过大）
                        if (prevY !== null && Math.abs(y - prevY) > 20) {
                            // 插入一个断开点
                            data.push({ x: null, y: null, isDiscontinuity: true });
                        }
                        
                        data.push({ x, y, isDiscontinuity: false });
                        prevY = y;
                    } else {
                        // 如果当前点无效，插入断开点
                        data.push({ x: null, y: null, isDiscontinuity: true });
                        prevY = null;
                    }
                } catch (e) {
                    console.error('函数计算错误：', e);
                    // 在错误点插入断开点
                    data.push({ x: null, y: null, isDiscontinuity: true });
                    prevY = null;
                }
            }
            return data;
        }

        // 绘制按钮点击事件
        document.getElementById('drawBtn').addEventListener('click', () => {
            const expr = document.getElementById('functionInput').value.trim();
            if (!expr) {
                alert('请输入函数解析式！');
                return;
            }
            const data = generateFunctionData(expr);
            if (data.length > 0) {
                functionChart.data.datasets[0].data = data;
                functionChart.update();
            }
        });

        // 示例函数点击事件
        document.querySelectorAll('.function-example').forEach(example => {
            example.addEventListener('click', () => {
                document.getElementById('functionInput').value = example.getAttribute('data-func');
                document.getElementById('drawBtn').click();
            });
        });

        // 初始化绘制示例函数
        document.getElementById('drawBtn').click();
    </script>
</body>
</html>